﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FMOD;
using System.IO;

namespace ChartEdit
{
    public class Audio
    {
        static FMOD.System soundSystem;
        static FMOD.System clapSystem;
        Sound sound, clap, metronome;
        Channel sfxChannel;
        Channel channel;

        static Audio()
        {
            Factory.System_Create( ref soundSystem );
            Factory.System_Create(ref clapSystem);
            soundSystem.init( 256, INITFLAG.NORMAL, IntPtr.Zero );
            clapSystem.init(16, INITFLAG.NORMAL, IntPtr.Zero);
        }

        public Audio( string fileName )
        {
            soundSystem.createSound(fileName, MODE.ACCURATETIME | MODE.LOOP_OFF | MODE.HARDWARE | MODE._2D | MODE.CREATESTREAM, ref sound);
            soundSystem.playSound(CHANNELINDEX.FREE, sound, true, ref channel);
            
            // for debug/recording
            //channel.setVolume( 0.5f );
        }

        public void DefineSyncSounds(string clapFileName, string metronomeFileName)
        {

            clapSystem.createSound(clapFileName, MODE.ACCURATETIME | MODE.LOOP_OFF | MODE.HARDWARE | MODE._2D | MODE.CREATESAMPLE, ref clap);
            soundSystem.createSound(metronomeFileName, MODE._2D | MODE.ACCURATETIME | MODE.HARDWARE | MODE.LOOP_OFF | MODE._2D | MODE.CREATESAMPLE, ref metronome);
            //sfxChannel = new List<Channel>();
        }

        public uint Length()
        {
            uint length = 0u;
            if (sound != null)
            {
                sound.getLength(ref length, TIMEUNIT.MS);
            }
            return length;
        }

        public uint Position()
        {
            uint pos = 0u;
            if (channel != null)
            {
                channel.getPosition(ref pos, TIMEUNIT.MS);
            }
            return pos;
        }

        public void SetPosition(uint pos)
        {
            if (channel != null)
            {
                channel.setPosition(pos, TIMEUNIT.MS);
            }
        }

        public void Clap(float start)
        {
            if (sfxChannel != null)
            {
                //clapSystem.playSound(CHANNELINDEX.FREE, clap, true, ref sfxChannel);
                //sfxChannel.setDelay(DELAYTYPE.DSPCLOCK_PAUSE, 10000u, 10000u);
                sfxChannel.setPaused(false);
                sfxChannel.setPosition((uint)(start*1000), TIMEUNIT.MS);
            }
        }

        public bool IsPlaying()
        {
            bool playing = false;
            bool paused = false;
            if (channel != null)
            {
                channel.isPlaying(ref playing);
                channel.getPaused(ref paused);
            }
            return (playing & !paused);
        }
        public void Play()
        {
            if (channel != null)
            {
                channel.setPaused(false);
            }
        }

        public void Pause()
        {
            if ( channel != null )
                channel.setPaused( true );
        }

        public void Stop()
        {
            if (channel != null)
                channel.stop();
        }

        public void SetSpeed( float speed )
        {
            ChannelGroup group = null;
            soundSystem.getMasterChannelGroup( ref group );

            group.setPitch( speed );
        }
        public void SetVolume(float volume)
        {
            ChannelGroup group = null;
            soundSystem.getMasterChannelGroup(ref group);

            group.setVolume(volume);
        }
        public float GetSpeed()
        {
            float speed = 0;
            if (channel!=null)
            {
                bool paused = true;
                channel.getPaused(ref paused);
                if (!paused)
                {
                    ChannelGroup group = null;
                    soundSystem.getMasterChannelGroup(ref group);
                    group.getPitch(ref speed);
                }
            }
            return speed;
        }
    }
}
